#include <Windows.h>
#include <tchar.h>
#include <assert.h>

//////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{	
	static const UINT ID_BTNSTATUP	= 1001;
	static const UINT ID_BTNREAD	= 1002;
	static const UINT ID_LABINFO	= 1003;
	
	static HWND hButton;
	switch (nMsg)
	{
		case WM_CREATE:
		{
			//--: Move Main wnd to center of screen
			RECT rtMainWnd;
			GetClientRect(hWnd, &rtMainWnd);
			UINT nSrnWidth		= GetSystemMetrics(SM_CXFULLSCREEN);
			UINT nSrnHeight		= GetSystemMetrics(SM_CYFULLSCREEN);
			UINT nWndWidth		= (rtMainWnd.right - rtMainWnd.left);
			UINT nWndHeight		= (rtMainWnd.bottom - rtMainWnd.top);
			UINT nLeft			= (nSrnWidth - nWndWidth) / 2;
			UINT nTop			= (nSrnHeight - nWndHeight) / 2;
			MoveWindow(hWnd, nLeft, nTop, nWndWidth, nWndHeight, TRUE);

			CreateWindow(_T("Button"), _T("Startup Notepad"), WS_VISIBLE|WS_CHILD, 0, 0, 150, 50, hWnd, (HMENU)ID_BTNSTATUP, 0, 0);
			CreateWindow(_T("Button"), _T("Get Class Info"), WS_VISIBLE|WS_CHILD, 200, 0, 150, 50, hWnd, (HMENU)ID_BTNREAD, 0, 0);
			CreateWindow(_T("STATIC"), _T(""), WS_VISIBLE|WS_CHILD, 0, 60, 800, 400, hWnd, (HMENU)ID_LABINFO, 0, 0);

			break;
		}
		case WM_COMMAND:
		{
			switch (wParam)
			{
				case ID_BTNSTATUP:
				{
					ShellExecute(hWnd, _T("Open"), _T("Notepad.exe"), NULL, NULL, SW_SHOW);
					Sleep(1000);

					HWND hWndNotePad = FindWindowEx(NULL, NULL, _T("Notepad"), NULL);
					SetWindowLongPtr(hWndNotePad, GWLP_USERDATA, 100);
					SetWindowLongPtr(hWndNotePad, GWLP_HWNDPARENT, (LONG)hWnd);
					break;
				}
				case ID_BTNREAD:
				{
					DWORD dwUser = GetWindowLongPtr(hWnd, GWLP_USERDATA);

					HWND hWndNotePad = FindWindowEx(NULL, NULL, _T("Notepad"), NULL);
					if (NULL != hWndNotePad && IsWindow(hWndNotePad))
					{
						int		nIndexList[]	= { GWL_EXSTYLE, GWL_STYLE, GWLP_WNDPROC, GWLP_HINSTANCE, GWLP_HWNDPARENT,
													GWLP_ID, GWLP_USERDATA, DWLP_DLGPROC, DWLP_MSGRESULT, DWLP_USER };
						int*	nValueList		= new int[sizeof(nIndexList) / sizeof(*nIndexList)];
						const TCHAR* szInfo[]	= { _T("Extend Style:\t	0x%06X\n"),
											        _T("Style:\t		0x%06X\n"),
													_T("WndProc:		0x%06X\n"),   
													_T("hInstance:		0x%06X\n"),
													_T("hParent:\t		0x%06X\n"),
													_T("ID:			0x%06X\n"),
													_T("UserData:		0x%06X\n"),
													_T("DlgProc:\t		0x%06X\n"),
													_T("MsgResult:		0x%06X\n"),
													_T("User:			0x%06X\n")};
						assert((sizeof(nIndexList) / sizeof(*nIndexList)) == (sizeof(szInfo) / sizeof(*szInfo)));
						
						TCHAR szClassInfo[1024] = {0};
						TCHAR szTemp[256];
						for (int ii = 0; ii < sizeof(nIndexList) / sizeof(*nIndexList); ii++)
						{
							nValueList[ii] = GetWindowLongPtr(hWndNotePad, nIndexList[ii]);
	
							TCHAR szTemp[256];
							_stprintf_s(szTemp, szInfo[ii], nValueList[ii]);
							_tcscat(szClassInfo, szTemp);
						}
						SetWindowText(GetDlgItem(hWnd, ID_LABINFO), szClassInfo);
						OutputDebugString(szClassInfo);
						delete[] nValueList;
					}
		
					break;
				}
			}
			break;
		}
		case WM_DESTROY:
		{
			PostQuitMessage(0);
			break;
		}
	}

	return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}

//////////////////////////////////////////////////////////////////////////
bool RegisterWndClass(HINSTANCE hInstance, const TCHAR* szClsName)
{
	WNDCLASSEX wcs		= {0};
	wcs.cbSize			= sizeof(WNDCLASSEX);
	wcs.hbrBackground	= (HBRUSH)GetStockObject(COLOR_APPWORKSPACE);
	wcs.lpszClassName	= szClsName;
	wcs.lpfnWndProc		= WndProc;
	wcs.hCursor			= LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
	wcs.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	wcs.style			= CS_VREDRAW|CS_HREDRAW;
	
	return (0 != RegisterClassEx(&wcs));
}

//////////////////////////////////////////////////////////////////////////
bool CreateMainWnd(HINSTANCE hInstance, const TCHAR* szClsName, const TCHAR* szWndCaption)
{
	if (NULL != szClsName && NULL != szWndCaption)
	{
		HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, szClsName, szWndCaption, WS_VISIBLE|WS_POPUPWINDOW|WS_CAPTION, 
								0, 0, 800, 480, NULL, NULL, hInstance, hInstance);
		if (NULL != hWnd && IsWindow(hWnd))
		{
			ShowWindow(hWnd, SW_SHOW);
			UpdateWindow(hWnd);
			return true;
		}
	}
	return false;
}

//////////////////////////////////////////////////////////////////////////
void RunMessageLoop()
{
	MSG Msg;
	while (true)
	{
		while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
		{
			if (WM_QUIT == Msg.message)
			{
				return;
			}

			TranslateMessage(&Msg);
			DispatchMessage(&Msg);
		}
	}
}
//////////////////////////////////////////////////////////////////////////
BOOL WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR szCmdLine, int nShowCmd)
{
	const TCHAR* szClsName		= _T("Win32App");
	const TCHAR* szWndCaption	= _T("Demo0028");

	if (RegisterWndClass(hInstance, szClsName))
	{
		if (CreateMainWnd(hInstance, szClsName, szWndCaption))
		{
			RunMessageLoop();
		}
	}

	return TRUE;
}